﻿using CoreShop.App.Payment.SxfPay;
using CoreShop.App.Units.Interface;
using CoreShop.Library;
using CoreShop.Model;
using CoreShop.Model.FromBody;
using CoreShop.PrintService;
using CoreShop.Services;
using CoreShop.Services.Services.System;
using FastMember;
using Loading;
using MySqlX.XDevAPI.Common;
using Newtonsoft.Json;
using SqlSugar;
using SqlSugar.Extensions;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Runtime.InteropServices.ComTypes;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Yitter.IdGenerator;
using static CoreShop.Library.GlobalEnumVars;
using static CoreShop.Services.PosRemoteServices;

namespace CoreShop.App
{
    public partial class frmOrderList : UIForm
    {
        private corecmsfoodordermaster SelectOrderMaster = null;
        private List<corecmsfoodsalemaster> orderMasters = new List<corecmsfoodsalemaster>();
        OpaqueCommand cmd = new OpaqueCommand();
        private bool IsAbnormal = false;//显示异常订单

        public frmOrderList(long mclasId, bool _IsAbnormal = false)
        {
            InitializeComponent();
            IsAbnormal = _IsAbnormal;
            if (_IsAbnormal)
            {
                this.MyFormTitle.Text = "异常订单";
                this.btnPayCheck.Visible = true;
            }
            this.dgvOrderList.AutoGenerateColumns = false;
            this.binOrders.DataSource = orderMasters;
            this.dgvOrderList.DataSource = this.binOrders;
            this.ShowFullScreen = AppConstVars.showFullScreen;
            //this.dateTimeRange.DoValueChanged += DoValueChanged;
            if (mclasId > 0)
            {
                var mClassInfo = new corecmsfoodorderclassServices().GetById(mclasId);
                if (mClassInfo != null)
                {
                    strNumber.Text = mClassInfo.classNumber;
                    dateTimeRange.DateTimeStar = mClassInfo.starDate.ToString("yyyy-MM-dd HH:mm:ss");
                }
            }
            else
            {
                dateTimeRange.DateTimeStar = CommFunc.ConvertToDateTime(DateTime.Now.ToString("yyyy-MM-dd") + " 00:00:00").ToString("yyyy-MM-dd HH:mm:ss");
            }

            dateTimeRange.DateTimeEnd = CommFunc.ConvertToDateTime(DateTime.Now.ToString("yyyy-MM-dd") + " 23:59:59").ToString("yyyy-MM-dd HH:mm:ss");
        }

        private void DoValueChanged(object sender, System.EventArgs e)
        {
            btnRefresh_Click(null,null);
        }

        private void uiButton1_Click(object sender, System.EventArgs e)
        {
            UIButton btn = (UIButton)sender;
            btn.Selected = true;
        }

        private void FOrders_Shown(object sender, System.EventArgs e)
        {
            BindComboBoxData();
            timer1.Start();
        }
        public void BindComboBoxData()
        {
            try
            {
                #region 
                this.ordertype.Items.Clear();
                var ordertypeListAll = EnumHelper.EnumToList<GlobalEnumVars.OrderBillType>();
                var ordertypeList = ordertypeListAll.Where(p => p.value < (int)GlobalEnumVars.OrderBillType.Deposit).ToList();
                ordertype.DataSource = ordertypeList;
                ordertype.DisplayMember = "description";
                ordertype.ValueMember = "value";
                if (ordertypeList.Count > 0) this.ordertype.SelectedIndex = 0;

                #endregion
            }
            catch (Exception)
            {
                throw;
            }
        }
        private void timer1_Tick(object sender, System.EventArgs e)
        {
            timer1.Stop();
            //ShowStatusForm(23);
            Thread.Sleep(100);
            LoadOrderList();
        }

        private Expressionable<corecmsfoodordermaster, corecmsuser, sysuser, corecmsfoodorderclass> GetExpressionable()
        {
            int? ordertype = null;
            if (this.ordertype != null) ordertype = CommFunc.ConvertToInt32(this.ordertype.SelectedValue);

            DateTime startDate = CommFunc.ConvertToDateTime(dateTimeRange.DateTimeStar);
            DateTime endDate = CommFunc.ConvertToDateTime(dateTimeRange.DateTimeEnd);
            string str = this.strNumber.Text;

            var where = Expressionable.Create<corecmsfoodordermaster, corecmsuser, sysuser, corecmsfoodorderclass>();
            
            if (ordertype > 0)
                where = where.And((a, u, su, c) => a.ordertype == ordertype);

            if (startDate != null)
                where = where.And((a, u, su, c) => a.orderDate > startDate);

            if (endDate != null)
                where = where.And((a, u, su, c) => a.orderDate < endDate);

            if (!string.IsNullOrEmpty(str))
            {
                var classModel = new corecmsfoodorderclassServices().AsQueryable().Where(p => p.classNumber == str).First();
                if (classModel != null)
                    where = where.And((a, u, su, c) => a.classId == classModel.id);
                else
                    where = where.And((a, u, su, c) => (a.orderNo.Contains(str) || a.number.Contains(str) || u.mobile.Contains(str) || u.cardNo.Contains(str)));
            }

            if (IsAbnormal)
            {
                var where1 = Expressionable.Create<corecmsfoodordermaster, corecmsfoodorderpayment>();
                if (startDate != null)
                    where1 = where1.And((a, p) => a.orderDate > startDate);

                if (endDate != null)
                    where1 = where1.And((a, p) => a.orderDate < endDate);

                where1 = where1.And((a, p) => p.outcomeType == (int)GlobalEnumVars.PayOutcomeType.Unknown);
                var orderIds = new corecmsfoodordermasterServices().AsQueryable()
                    .LeftJoin<corecmsfoodorderpayment>((a, p) => a.orderId == p.orderId)
                    .Where(where1.ToExpression()).Select((a, p) => a.orderId).ToList();

                if (orderIds.Count > 0)
                    where = where.And((a, u, su, c) => orderIds.Contains(a.orderId));
                else
                    where = where.And((a, u, su, c) => a.orderId == -1);
            }

            return where;
        }

        private void LoadOrderList()
        {
            int count = 0;
            SelectOrderMaster = null;
            //orderMasters = new corecmsfoodordermasterServices().SelectByOrdertype(ref count, 1, 200, ordertype, dtStartDate, dtEndDate, str, 0, IsAbnormal);
            orderMasters = new corecmsfoodordermasterServices().SelectByOrdertype(ref count, 1, 200, GetExpressionable());
            this.binOrders.DataSource = orderMasters;
            this.dgvOrderList.DataSource = null;
            this.dgvOrderList.DataSource = this.binOrders; 
            this.sum.Text = orderMasters.Count.ToString();
            this.amount.Text = orderMasters.Sum(p => p.sumAllAmount).ToString();
            if (orderMasters.Count > 0)
            {
                var masterFirst = orderMasters.First();
                GetSelectOrderMaster(masterFirst.orderId);
                LoadOrderDetail();
            }            
        }

        private void BindOrderItemInfo(OrderItemInfo info, corecmsfoodsalemaster item)
        {
            info.Tags.Clear();
            info.id = item.orderId;
            info.paymentId = 0;
            info.Name = item.orderNo.ToString();
            if (!item.isUpload) info.AddTag("未上传");
            info.Order = EnumHelper.GetEnumByValue<GlobalEnumVars.OrderPayStatus>(item.status.ObjToInt(0));
            info.OrderID = item.orderDate.ToString();
            if (item.sourceType == (int)FoodOrderSourceType.Meituan)
                info.OrderID = EnumHelper.GetDescByValue<GlobalEnumVars.FoodOrderSourceType>(item.sourceType.ObjToInt(0));
            info.MoneyFrom = item.sumAllAmount.ToString();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GetSelectOrderMaster(long orderId)
        {
            SelectOrderMaster = new corecmsfoodordermasterServices().AsQueryable().Where(p => p.orderId == orderId).First();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Detail_OnClick(object sender, System.EventArgs e)
        {
            OrderItemInfo itemInfo = (OrderItemInfo)sender;
            SelectOrderMaster = new corecmsfoodordermasterServices().AsQueryable().Where(p => p.orderId == itemInfo.id).First();
            LoadOrderDetail();
        }

        private void LoadOrderDetail()
        {
            btnSendOrder.Enabled = false;
            layOrderDetail.Clear();
            if (SelectOrderMaster == null) return;

            List<corecmsfoodorderdetail> orderDetails = new corecmsfoodorderdetailServices().AsQueryable().Where(p => p.orderId == SelectOrderMaster.orderId).ToList();

            btnRefund.Visible = false;
            btnPrintLabel.Visible = true;
            if (SelectOrderMaster.status == (int)GlobalEnumVars.OrderPayStatus.IsPay && SelectOrderMaster.sourceType != (int)FoodOrderSourceType.Meituan)
            {
                if (SelectOrderMaster.deskId == 0 || SelectOrderMaster.sourceType == (int)FoodOrderSourceType.Wechat || SelectOrderMaster.sourceType == (int)FoodOrderSourceType.Alipay)
                    btnRefund.Visible = true;
                else btnSettlementUn.Visible = true;
            }
            else btnPrintLabel.Visible = false;

            this.foodInfo.Text = SelectOrderMaster.orderNo + "商品信息";
            this.foodInfoCount.Text = "共" + SelectOrderMaster.sumQuantity + "项：合计￥" + SelectOrderMaster.sumAmount.ToString();

            this.orderNo.Text = SelectOrderMaster.orderNo;
            this.orderDate.Text = SelectOrderMaster.orderDate.ToString();
            this.status.Text = EnumHelper.GetEnumByValue<GlobalEnumVars.OrderPayStatus>(SelectOrderMaster.status.ObjToInt(0));            
            this.number.Text = SelectOrderMaster.number.ToString();
            var user = new sysuserServices().AsQueryable().Where(p => p.id == SelectOrderMaster.sysUserId).First();
            if (user != null) this.sysUserName.Text = user.userName;
            var orderPays = new corecmsfoodorderpaymentServices().AsQueryable().Where(p => p.orderId == SelectOrderMaster.orderId).ToList();
            if (orderPays.Count > 0)
            {
                var payIds = orderPays.Select(p => p.paymentId).ToList();
                var orderPaysList = new corecmspaymentsService().AsQueryable().Where(p=> payIds.Contains(p.id)).ToList();
                layPayList.Visible = false;
                layPayList.Clear();
                foreach (var item in orderPays)
                {
                    var orderPaysInfo = orderPaysList.Find(p=>p.id == item.paymentId);
                    if (orderPaysInfo != null)
                    {
                        UPaymentnfo info = new UPaymentnfo();
                        info.Name = orderPaysInfo.name;
                        info.Amount = item.payAmount.ToString();
                        info.IsAbnormal = IsAbnormal;
                        if ((IsAbnormal) && (item.outcomeType == (int)GlobalEnumVars.PayOutcomeType.Unknown))
                            info.abnormal = "手动确认";

                        UIMenuItemPay menu = new UIMenuItemPay(info);
                        menu.SetMinSize();
                        layPayList.Add(menu);
                    }
                }
                layPayList.Visible = true;
            }
            if (!SelectOrderMaster.isUpload.ObjToBool()) btnSendOrder.Enabled = true;
            decimal sumRealAmount = SelectOrderMaster.sumAmount + SelectOrderMaster.sumTaskAmount + SelectOrderMaster.sumFeedAmount;
            this.sumRealAmount.Text = sumRealAmount.ToString();//商品价格合计
            this.discountAmount.Text = (SelectOrderMaster.sumAmount - SelectOrderMaster.sumRealAmount).ToString();//订单金额
            this.sumReduceAmount.Text = (SelectOrderMaster.sumRealAmount + SelectOrderMaster.sumTaskAmount + SelectOrderMaster.sumFeedAmount - SelectOrderMaster.sumAllAmount).ToString();//顾客应付
            this.sumAllAmount.Text = SelectOrderMaster.sumAllAmount.ToString();//优惠合计
            if (orderDetails.Count > 0)
            {
                layOrderDetail.Visible = false;
                foreach (var item in orderDetails)
                {
                    MenuItemInfo info = new MenuItemInfo();
                    info.Name = item.name;
                    info.Count = item.quantity.ToString();
                    info.Money = item.realAmount.ToString();
                    info.UnitName = item.unitName;
                    info.Price = item.price.ToString("0.0##");
                    info.RealPrice = item.realPrice.ToString("0.0##");
                    info.Code = item.code;
                    info.IsReturning = false;
                    info.RowId = item.rowId.ToString();
                    if (item.quantity < 0)
                    {
                        info.IsReturning = true;
                        info.Tags.Add(item.remark);
                    }
                    UIMenuItem menu = new UIMenuItem(info);
                    menu.SetMinSize();
                    layOrderDetail.Add(menu);
                    StatusFormStepIt();
                }
                layOrderDetail.Visible = true;
                HideStatusForm();
            }
            LoadOrderMember();
        }

        private void LoadOrderMember()
        {
            number.Text = string.Empty;
            userName.Text = string.Empty;
            userPoint.Text = string.Empty;
            if (SelectOrderMaster == null) return;
            userPoint.Text = SelectOrderMaster.userPoint.ToString();
            if (SelectOrderMaster.userId == 0) return;
            var memberInfo = new corecmsuserServices().GetById(SelectOrderMaster.userId); ;
            if (memberInfo != null)
            {
                number.Text = memberInfo.mobile;
                userName.Text = memberInfo.userName;
            }
        }

        private void btnHomePage_Click(object sender, System.EventArgs e)
        {
            this.Close();
        }

        private void btnPrint_Click(object sender, EventArgs e)
        {
            try
            {
                if (SelectOrderMaster == null)
                {
                    UIMessageBox.Show("请选择一个单据后再打印", "提示:", UIStyle.Green, UIMessageBoxButtons.OK);
                    return;
                }
                if (!ProcessUtil.GetUserRole(GlobalEnumVars.UserRoleType.isPrintRepair, 0)) return;
                SelectOrderMaster.moreName = "(补)";
                new PrintServices().SetPrintOrdering(SelectOrderMaster, isPrintPreview.Checked);                
                new PrintServices().SetPrintSettlement(SelectOrderMaster, isPrintPreview.Checked);
            }
            catch (Exception ex)
            {
                UIMessageBox.Show(ex.Message, "提示:", UIStyle.Green, UIMessageBoxButtons.OK);
            }
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        
        private void btnSettlementUn_Click(object sender, EventArgs e)
        {
            var orderMaster = GetOrdermaster();
            if (orderMaster == null) return;
            try
            {
                var frm = new frmFoodRefund(orderMaster);
                frm.Owner = this;
                if (frm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    //BindOrdering(orderingMaster.orderId);
                }
                frm.Dispose();
            }
            catch { }
        }

        private string GetMenuItemName(long orderingId)
        {
            return "uiMenuItem_" + orderingId.ToString();
        }

        private corecmsfoodordermaster GetOrdermaster()
        {
            if (SelectOrderMaster == null)
            {
                UIMessageBox.Show("请选择一个单据进行退单", "提示:", UIStyle.Green, UIMessageBoxButtons.OK);
                return null;
            }
            var orderMaster = new corecmsfoodordermasterServices().GetById(SelectOrderMaster.orderId);
            if (orderMaster == null)
            {
                UIMessageBox.Show("没有可退单的数据。", "退货出错:", UIStyle.Green, UIMessageBoxButtons.OK);
                return null;
            }
            string msg = "";
            if (orderMaster.status != (int)GlobalEnumVars.OrderPayStatus.IsPay)
            {
                msg = "订单状态为[" + EnumHelper.GetEnumByValue<GlobalEnumVars.OrderPayStatus>(orderMaster.status.ObjToInt(0)) + "]，不能退单。";
                UIMessageBox.Show(msg, "出错:", UIStyle.Green, UIMessageBoxButtons.OK);
                return null;
            }
            if (!ProcessUtil.GetUserRole(GlobalEnumVars.UserRoleType.isOrderRefund, 0)) return null;
            return orderMaster;
        }

        private async void btnRefund_Click(object sender, EventArgs e)
        {
            var orderMaster = GetOrdermaster();
            if (orderMaster == null) return;
            var orderMasterRef = new corecmsfoodordermasterServices().AsQueryable().Where(p => p.sourceId == orderMaster.orderId).ToList();
            if ((orderMasterRef != null) && (orderMasterRef.Count > 0))
            {
                UIMessageBox.Show("该销售单已退货，不能重复退货。", "退货出错:", UIStyle.Green, UIMessageBoxButtons.OK);
                return;
            }
            string msg = "确认要对选择的单据进行退单吗？";
            if (!ShowAskDialog(msg)) return;
            cmd.ShowOpaqueLayer(pnl_botton, 125, true);
            try
            {
                OrderRefundPost orderRefund = new OrderRefundPost();
                orderRefund.orderMaster = orderMaster;
                orderRefund.orderDetail = new corecmsfoodorderdetailServices().AsQueryable().Where(p => p.orderId == orderMaster.orderId).ToList();
                orderRefund.orderPayment = new corecmsfoodorderpaymentServices().AsQueryable().Where(p => p.orderId == orderMaster.orderId).ToList();

                if (!(await OrderRefundUtil.SetRefundPayment(this, orderRefund))) return;
                if (!new corecmsfoodordermasterServices().SetOrderRefund(orderRefund, AppConstVars.classId, AppConstVars.sysStore, ref msg))
                {
                    UIMessageBox.Show(msg, "生成退款订单数据失败:", UIStyle.Green, UIMessageBoxButtons.OK);
                    return;
                }
                orderMaster.status = (int)GlobalEnumVars.OrderPayStatus.Refund;
                orderMaster.isUpload = false;
                var bl = new corecmsfoodordermasterServices().InsertOrUpdate(orderMaster);
                if (!bl)
                {
                    UIMessageBox.Show("保存数据出错", "保存数据出错:", UIStyle.Green, UIMessageBoxButtons.OK);
                    return;
                }
                bl = new corecmsfoodorderdetailServices().Update(a => new corecmsfoodorderdetail()
                {
                    dataType = (int)Library.GlobalEnumVars.OrderingDataType.Refund
                }, a => a.orderId == orderMaster.orderId);
                SelectOrderMaster = orderMaster;
                new PrintServices().SetPrintSettlement(orderRefund.orderMaster, false);
                LoadOrderList();
                //RefreshOrderRow();
                LoadOrderDetail();
                OrderApiUtil.SendOrderUp(AppConstVars.sysUser, AppConstVars.sysStore, AppConstVars.classNumber, orderRefund.orderMaster.orderId);
                UIMessageBox.Show("订单退款成功", "提示:", UIStyle.Green, UIMessageBoxButtons.OK);
            }
            catch (Exception ex) { }
            finally {
                cmd.HideOpaqueLayer();
            }
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            LoadOrderList();
        }

        private void FOrderList_Load(object sender, EventArgs e)
        {

        }

        private void btnPrintLabel_Click(object sender, EventArgs e)
        {
            if (SelectOrderMaster == null)
            {
                UIMessageBox.Show("请选择一个单据后再打印", "提示:", UIStyle.Green, UIMessageBoxButtons.OK);
                return;
            }
            new PrintServices().SetPrintLabel(SelectOrderMaster, isPrintPreview.Checked);
        }

        private async void btnSendOrder_Click(object sender, EventArgs e)
        {
            //上传订单数据
            var result = await OrderApiUtil.SendOrderThread(AppConstVars.sysUser, AppConstVars.sysStore, AppConstVars.classNumber, SelectOrderMaster.orderId,true);
            UIMessageBox.Show(result.msg, "提示:", UIStyle.Green, UIMessageBoxButtons.OK);
            LoadOrderList();
        }

        private void dgvFoodList_SelectionChanged(object sender, EventArgs e)
        {
            SelectOrderMaster = null;
            if (dgvOrderList.SelectedRows.Count == 1)
            {
                GetSelectOrderMaster(CommFunc.ConvertToInt64(dgvOrderList.SelectedRows[0].Cells["orderId"].Value));
            }
            LoadOrderDetail();
        }

        private async Task SetOrderPayCheck()
        {
            var orderList = this.binOrders.DataSource as List<corecmsfoodsalemaster>;
            bool isSaveTasklog = false;
            if ((orderList == null) || (orderList.Count == 0))
            {
                UIMessageBox.Show("没有要检测的异常订单", "提示:", UIStyle.Green, UIMessageBoxButtons.OK);
                return;
            }
            if (!ShowAskDialog("确定要检测所有异常订单吗？")) return;
            foreach (var order in orderList)
            {
                var orderPayList = new corecmsfoodorderpaymentServices().AsQueryable()
                    .Where(p => p.orderId == order.orderId && p.outcomeType == (int)GlobalEnumVars.PayOutcomeType.Unknown).ToList();
                foreach (var orderPay in orderPayList)
                {
                    if (orderPay.paymentId == (int)GlobalEnumVars.Payment.alipay
                        || orderPay.paymentId == (int)GlobalEnumVars.Payment.wechatpay
                        || orderPay.paymentId == (int)GlobalEnumVars.Payment.paymix
                        || orderPay.paymentId == (int)GlobalEnumVars.Payment.unionPay)
                    {
                        var result = await SetSxfPayCheck(order, orderPay);//移动支付检测
                        if (!result) isSaveTasklog = true;
                    }
                    else
                    if (orderPay.paymentId == (int)GlobalEnumVars.Payment.balancepay)
                    {

                    }
                }                
            }
            LoadOrderList();
            if (isSaveTasklog)
            {
                if (!ShowAskDialog("检测后还有异常订单，要查看测试结果的日志吗？")) return;
                var frm = new frmSystemLog();
                frm.ShowDialog();
                frm.Dispose();
            } 
            else
                UIMessageBox.Show("检测完成。", "提示:", UIStyle.Green, UIMessageBoxButtons.OK);
        }

        private async Task<bool> SetSxfPayCheck(corecmsfoodsalemaster orderMaster, corecmsfoodorderpayment payModel)
        {
            try
            {
                SxfPay sxfPay = new SxfPay(AppConstVars.systemsetup, AppConstVars.payaccount);
                var tradeResult = await sxfPay.tradeQueryAsync(payModel.paymentCode);
                if (tradeResult.isSuccess)
                {
                    payModel.outcomeType = (int)GlobalEnumVars.PayOutcomeType.Confirmed;
                    new corecmsfoodorderpaymentServices().UpdateAsync(payModel);
                    return true;
                }
                else
                {
                    string sResult = $"订单号<{orderMaster.orderNo}>检查结果->{JsonConvert.SerializeObject(tradeResult)}";
                    await new corecmsprinttasklogServices().InsertAsync(sResult);                    
                }
            }
            catch (Exception ex)
            {
                UIMessageBox.Show(ex.Message, "检测出错:", UIStyle.Green, UIMessageBoxButtons.OK);
            }
            return false;
        }

        private async void btnPayCheck_Click(object sender, EventArgs e)
        {
            try
            {
                cmd.ShowOpaqueLayer(pnl_payinfo, 125, true);
                await SetOrderPayCheck();
            }
            catch (Exception ex) { }
            finally
            {
                cmd.HideOpaqueLayer();
            }
        }
    }
}
